// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Components/GameFrameworkComponent.h"

#include "LyraHealthComponent.generated.h"

#define UE_API LYRAGAME_API

class ULyraHealthComponent;

class ULyraAbilitySystemComponent;
class ULyraHealthSet;
class UObject;
struct FFrame;
struct FGameplayEffectSpec;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLyraHealth_DeathEvent, AActor*, OwningActor); // 声明动态多播委托：死亡事件
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FLyraHealth_AttributeChanged, ULyraHealthComponent*, HealthComponent, float, OldValue, float, NewValue, AActor*, Instigator); // 声明动态多播委托：属性改变

/**
 * ELyraDeathState
 *
 *	定义当前的死亡状态。
 */
UENUM(BlueprintType)
enum class ELyraDeathState : uint8
{
	NotDead = 0, // 未死亡
	DeathStarted, // 死亡开始
	DeathFinished // 死亡完成
};

/**
 * ULyraHealthComponent
 *
 *	用于处理与健康相关的任何内容的Actor组件。
 */
UCLASS(MinimalAPI, Blueprintable, Meta=(BlueprintSpawnableComponent))
class ULyraHealthComponent : public UGameFrameworkComponent
{
	GENERATED_BODY()

public:

	UE_API ULyraHealthComponent(const FObjectInitializer& ObjectInitializer);

	// 如果指定Actor上存在健康组件，则返回该组件。
	UFUNCTION(BlueprintPure, Category = "Lyra|Health")
	static ULyraHealthComponent* FindHealthComponent(const AActor* Actor) { return (Actor ? Actor->FindComponentByClass<ULyraHealthComponent>() : nullptr); } // 查找健康组件

	// 使用能力系统组件初始化组件。
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	UE_API void InitializeWithAbilitySystem(ULyraAbilitySystemComponent* InASC);

	// 取消初始化组件，清除对能力系统的任何引用。
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	UE_API void UninitializeFromAbilitySystem();

	// 返回当前健康值。
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	UE_API float GetHealth() const;

	// 返回当前最大健康值。
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	UE_API float GetMaxHealth() const;

	// 返回当前健康值在范围[0.0, 1.0]内。
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	UE_API float GetHealthNormalized() const;

	/**
	 * 获取死亡状态
	 */
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	ELyraDeathState GetDeathState() const { return DeathState; } // 返回死亡状态

	/**
	 * 检查是否死亡或正在死亡
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Lyra|Health", Meta = (ExpandBoolAsExecs = "ReturnValue"))
	bool IsDeadOrDying() const { return (DeathState > ELyraDeathState::NotDead); } // 返回是否死亡或正在死亡

	// 开始所有者的死亡序列。
	UE_API virtual void StartDeath();

	// 结束所有者的死亡序列。
	UE_API virtual void FinishDeath();

	// 应用足够的伤害来杀死所有者。
	UE_API virtual void DamageSelfDestruct(bool bFellOutOfWorld = false);

public:

	// 健康值改变时触发的委托。在客户端调用，但发起者可能无效
	UPROPERTY(BlueprintAssignable)
	FLyraHealth_AttributeChanged OnHealthChanged; // 健康改变委托

	// 最大健康值改变时触发的委托。在客户端调用，但发起者可能无效
	UPROPERTY(BlueprintAssignable)
	FLyraHealth_AttributeChanged OnMaxHealthChanged; // 最大健康改变委托

	// 死亡序列开始时触发的委托。
	UPROPERTY(BlueprintAssignable)
	FLyraHealth_DeathEvent OnDeathStarted; // 死亡开始委托

	// 死亡序列完成时触发的委托。
	UPROPERTY(BlueprintAssignable)
	FLyraHealth_DeathEvent OnDeathFinished; // 死亡完成委托

protected:

	UE_API virtual void OnUnregister() override;

	/**
	 * 清除游戏标签
	 */
	UE_API void ClearGameplayTags();

	/**
	 * 处理健康改变
	 */
	UE_API virtual void HandleHealthChanged(AActor* DamageInstigator, AActor* DamageCauser, const FGameplayEffectSpec* DamageEffectSpec, float DamageMagnitude, float OldValue, float NewValue);
	/**
	 * 处理最大健康改变
	 */
	UE_API virtual void HandleMaxHealthChanged(AActor* DamageInstigator, AActor* DamageCauser, const FGameplayEffectSpec* DamageEffectSpec, float DamageMagnitude, float OldValue, float NewValue);
	/**
	 * 处理生命值耗尽
	 */
	UE_API virtual void HandleOutOfHealth(AActor* DamageInstigator, AActor* DamageCauser, const FGameplayEffectSpec* DamageEffectSpec, float DamageMagnitude, float OldValue, float NewValue);

	/**
	 * 死亡状态复制时调用
	 */
	UFUNCTION()
	UE_API virtual void OnRep_DeathState(ELyraDeathState OldDeathState);

protected:

	// 此组件使用的能力系统。
	UPROPERTY()
	TObjectPtr<ULyraAbilitySystemComponent> AbilitySystemComponent; // 能力系统组件

	// 此组件使用的健康集。
	UPROPERTY()
	TObjectPtr<const ULyraHealthSet> HealthSet; // 健康集

	// 用于处理死亡的复制状态。
	UPROPERTY(ReplicatedUsing = OnRep_DeathState)
	ELyraDeathState DeathState; // 死亡状态
};

#undef UE_API